package com.jpa.config;

import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager;
import com.atomikos.spring.AtomikosDataSourceBean;
import org.jooq.DSLContext;
import org.jooq.SQLDialect;
import org.jooq.impl.DSL;
import org.jooq.impl.DataSourceConnectionProvider;
import org.jooq.impl.DefaultConfiguration;
import org.jooq.impl.DefaultExecuteListenerProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jooq.ExceptionTranslatorExecuteListener;
import org.springframework.boot.autoconfigure.jooq.SpringTransactionProvider;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.transaction.jta.JtaTransactionManager;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @Autor: songfei
 * @Description:
 * @Date: Created in 21:47 2025/3/17
 **/
@Configuration
public class MultitenantConfiguration {
    @Value("${defaultTenant:ISIC}")
    private String defaultTenant;

    @Bean
    @ConfigurationProperties(prefix = "tenants")
    public DataSource dataSource() {
        File[] files = Paths.get("allTenants").toFile().listFiles();
        Map<Object, Object> resolvedDataSources = new HashMap<>();

        for (File propertyFile : files) {
            try {
                Properties tenantProperties = new Properties();

                tenantProperties.load(new FileInputStream(propertyFile));
                String tenantId = tenantProperties.getProperty("name");
                AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean();
                dataSource.setUniqueResourceName(tenantId);
                dataSource.setXaDataSourceClassName(tenantProperties.getProperty("datasource.driver-class-name"));
                Properties properties = new Properties();
                properties.setProperty("url", tenantProperties.getProperty("datasource.url"));
                properties.setProperty("user", tenantProperties.getProperty("datasource.username"));
                properties.setProperty("password", tenantProperties.getProperty("datasource.password"));
                dataSource.setXaProperties(properties);

                resolvedDataSources.put(tenantId, dataSource);
            } catch (IOException exp) {
                throw new RuntimeException("Problem in tenant datasource:" + exp);
            }


        }

        AbstractRoutingDataSource dataSource = new MultitenantDataSource();
        dataSource.setDefaultTargetDataSource(resolvedDataSources.get(defaultTenant));
        dataSource.setTargetDataSources(resolvedDataSources);

        dataSource.afterPropertiesSet();
        return dataSource;
    }

    @Bean
    public JtaTransactionManager transactionManager() {
        return new JtaTransactionManager(new UserTransactionImp(), new UserTransactionManager());
    }

    @Bean
    public DSLContext dslContext(org.jooq.Configuration configuration) {
        return DSL.using(configuration);
    }

    @Bean
    public org.jooq.Configuration configuration(DataSourceConnectionProvider provider) {
        DefaultConfiguration configuration = new DefaultConfiguration();
        configuration.setSQLDialect(SQLDialect.POSTGRES);
        configuration.setConnectionProvider(provider);
        configuration.setExecuteListenerProvider(new DefaultExecuteListenerProvider(ExceptionTranslatorExecuteListener.DEFAULT));
        configuration.setTransactionProvider(new SpringTransactionProvider(transactionManager()));
        return configuration;
    }

    @Bean
    public DataSourceConnectionProvider dataSourceConnectionProvider(DataSource dataSource) {
        return new DataSourceConnectionProvider(dataSource);
    }
}
